--------------------------------------------------------------------------
Quick CDrom explanation...                                     2000/doomed

There's a *LOT* missing here, and the other half might be incorrect, so
i won't take any responsibility for strange stuff happening. It should
give you some pointers in the right direction for your own CD explorations
though. More might follow at some later time..
--------------------------------------------------------------------------
CDREG0 = $1f801800
CDREG1 = $1f801801
CDREG2 = $1f801802
CDREG3 = $1f801803
--------------------------------------------------------------------------
CDREG0   write    : 0 - to send a command
                    1 - to get the result
         read     : I/O status?
                    bit 0- 0 REG1 command send
                         - 1 REG1 data read
                    bit 1- 0 data transfer finished
                           1 data transfer ready/in progress
                    bit 7- 1 command being processed.

CDREG1   write    : command
         read     : results

CDREG2   write    : send arguments
         write    : 7 = flush arg buffer?

CDREG3   write    : 7 = flush irq
         read     : hi nibble: ?
                    low nibble: interrupt status
--------------------------------------------------------------------------
Modes for SetMode:
M_Speed        bit 7      0: normal speed  1: double speed
M_Strsnd       bit 6      0: ADPCM off     1: ADPCM on
M_Size         bit 5      0: 2048 byte     1: 2340 byte
M_Size2        bit 4      0: -             1: 2328 byte
M_SF           bit 3      0: Channel off   1: Channel on
M_Report       bit 2      0: Report off    1: Report on
M_AutoPause    bit 1      0: AutoPause off 1: AutoPause on
M_CDDA         bit 0      0: CD-DA off     1: CD-DA on

These modes can be set using the setmode command. 
--------------------------------------------------------------------------
Status bits:
Play       	bit 7      playing CD-DA
Seek       	bit 6      seeking
Read       	bit 5      reading data sectors
ShellOpen  	bit 4      once shell open
SeekError  	bit 3      seek error detected
Standby    	bit 2      spindle motor rotating
Error      	bit 1      command error detected

These are the bit values for the status byte recieved from CD commands.
--------------------------------------------------------------------------
Interrupt values:
NoIntr      $00        No interrupt
DataReady   $01        Data Ready
Acknowledge $02        Command Complete
Complete    $03        Acknowledge
DataEnd     $04        End of Data Detected
DiskError   $05        Error Detected

These are returned in the low nibble of CDREG3. First write a 1 to CDREG0
before reading CDREG3. When a command is completed it returns 3.
To acknowledge an irq value after you've handled it, write a 1 to CDREG0
then a 7 to both CDREG2 and CDREG3. Another interrupt may be queued, so
you should check CDREG3 again if 0 or if there's another interrupt to
be handled.
--------------------------------------------------------------------------
Sync           $00         -                 status
Nop            $01         -                 status
Setloc         $02         min,sec,sector    status
Play           $03    B    -                 status
Forward        $04    B    -                 status
Backward       $05    B    -                 status
ReadN          $06    B    -                 status
Standby        $07    B    -                 status
Stop           $08    B    -                 status
Pause          $09    B    -                 status
Init           $0a         -                 status
Mute           $0b         -                 status
Demute         $0c         -                 status
Setfilter      $0d         file,channel      status
Setmode        $0e         mode              status
Getparam       $0f         -                 status,mode,file?,chan?,?,?
GetlocL        $10         -                 min,sec,sector,mode,file,channel
GetlocP        $11         -                 track,index,min,sec,frame,amin,
                                                 asec,aframe
GetTN          $13         -                 status,first,total (BCD)
GetTD          $14         track(BCD)        status,min,sec (BCD)
SeekL          $15    B    *                 status
SeekP          $16    B    *                 status
Test           $19         #                 depends on parameter
ID             $1A    B    -                 success,flag1,flag2,00
                                                 4 letters of ID (SCEx)
ReadS          $1B    B    -                 status
Reset          $1C         -                 status
ReadTOC        $1E    B?   -                 status

* These commands' targets are set using Setloc.
# Command 19 is really a portal to another set of commands.

B means blocking.  These commands return an immediate result saying the
command was started, but you need to wait for an IRQ in order to get
real results.

Command descriptions:
00 Sync:       Command does not succeed until all other commands complete.
               This can be used for synchronization - hence the name.
01 Nop:        Does nothing; use this if you just want the status.
02 Setloc:     This command, with its parameters, sets the target for
               commands with a * for their parameter list.
03 Play:       Plays audio sectors from the last point seeked.  This is
               almost identical to CdlReadS, believe it or not.  The main
               difference is that this does not trigger a completed read
               IRQ.  CdlPlay may be used on data sectors.  However, all
               sectors from data tracks are treated as 00, so no sound is
               played.  As CdlPlay is reading, the audio data appears in
               the sector buffer, but is not reliable.  Game Shark
               "enhancement CDs" for the 2.x and 3.x versions used this
               to get around the PSX copy protection.
04 Forward:    Seek to next track ?
05 Backward:   Seek to beginning of current track, or previous track if
               early in current track (like a CD player's back button)
06 ReadN:      Read with retry.  Each sector causes an IRQ (type 1) if
               ModeRept is on (I think).  ReadN and ReadS cause errors if
               you're trying to read a non-PSX CD or audio CD without a
               mod chip.
07 Standby:    CD-ROM aborts all reads and playing, but continues
               spinning.  CD-ROM does not attempt to keep its place.
08 Stop:       Stops motor.  Official way to restart is 0A, but almost
               any command will restart it.
09 Pause:      Like Standby, except the point is to maintain the current
               location within reasonable error.
0A Init:       Multiple effects at once.  Setmode = 00, Standby, abort
               all commands.
0B Mute:       Turn off CDDA stream to SPU.
0C Demute:     Turn on CDDA streaming to SPU.
0D Setfilter:  Automatic ADPCM (CD-ROM XA) filter ignores sectors except
               those which have the same channel and file (parameters)
               in their subheader area.  This is the mechanism used to
               select which of multiple songs in a single XA to play.
               Setfilter does not affect actual reading (sector reads
               still occur for all sectors).
0E Setmode:    Sets parameters such as read mode and spin speed.  See
               chart above the command list.
0F Getparam:   ??? returns status, mode, file, channel, ?, ?
10 GetlocL:    Retrieves first 6 (8?) bytes of last read sector (header)
               This is used to know where the sector came from, but is
               generally pointless in 2340 byte read mode.  All results
               are in BCD ($12 is considered track twelve, not eighteen)
               Command may execute concurrently with a read or play
               (GetlocL returns results immediately).
11 GetlocP:    Retrieves 8 of 12 bytes of sub-Q data for the last-read
               sector.  Same purpose as GetlocL, but more powerful, and
               works while playing audio.  All results are in BCD.
                   track:  track number ($AA for lead-out area)
                   index:  index number (INDEX lines in CUE sheets)
                   min:    minute number within track
                   sec:    second number within track
                   frame:  sector number within "sec" (0 to 74)
                   amin:   minute number on entire disk
                   asec:   second number on entire disk
                   aframe: sector number within "asec" (0 to 74)
13 GetTN:      Get first track number and number of tracks in the TOC.
14 GetTD:      Gets start of specified track (does it return sector??)
15 SeekL:      Seek to Setloc's location in data mode (can only seek to
               data sectors, but is accurate to the sector)
16 SeekP:      Seek to Setloc's location in audio mode (can seek to
               any sector, but is only accurate to the second)
19 Test:       This function has many subcommands that are completely
               different.
1A ID:         Returns copy protection status.  StatError for invalid
               data CD, StatStandby for valid PSX CD or audio CD.  The
               following bits I'm unsure about, but I think the 3rd
               byte has $80 bit for "CD denied" and $10 bit for
               "import".  $80 = copy, $90 = denied import, $10 =
               accepted import (Yaroze only).  The 5th through 8th
               bytes are the SCEx ASCII string from the CD. 
1B ReadS:      Read without automatic retry.
1C Reset:      Same as opening and closing the drive door.
1E ReadTOC:    Reread the Table of Contents without reset. 

-----------------------------------------------------------------------
--------------------------------------------------------------------------
To send a command:

- First send any arguments by writing 0 to CDREG0, then all arguments
  sequentially to CDREG2

- Then write 0 to CDREG0, and the command to CDREG1.

To wait for a command to complete:

- Wait until a CDrom irq occurs (bit 3 of the interrupt regs) The cause
  of the cdrom irq is in the low nibble of CDREG3. This is usually 3
  on a succesful comletion. Failure to complete the command will result
  in a 5. If you don't wish to use irq's you can just check for the
  low nibble of cdreg3 to become something other than 0, but make sure
  it doesn't get cleared in any irq setup by the bios or some such.

To Get the results

- Write a 1 to CDREG0, then read CDREG0, If bit 5 is set, read a return
  value from CDREG1, then read CDREG0 again repeat until bit 5 goes low.

To Clear the irq

- After command completion the irq cause should be cleared, do this by
  writing a 1 to CDREG0 then 7 to CDREG2 and CDREG3. My guess is that
  the write to CDREG2 clears the arguments previously set from some
  buffer.
  Note that irq's are queued, and if you clear the current, another may
  come up directly..
--------------------------------------------------------------------------
To init the CD:

-Flush all irq's
-CDREG0=0
-CDREG3=0
-Com_Delay=4901 ($1f801020)
-Send 2 NOP's
-Command $0a, no args.              (<- what's this??)
-Demute
--------------------------------------------------------------------------
To set up the cd for audio playback, some weird init stuff needs to be
done:

CDREG0=2
CDREG2=$80
CDREG3=0
CDREG0=3
CDREG1=$80
CDREG2=0
CDREG3=$20

Also don't forget to init the SPU. (CDvol and CD enable especially)
--------------------------------------------------------------------------
You should not send some commands while the CD is seeking. (ie. status
returns with bit 6 set.) Thing is that the status only gets updated after
a new command. I haven't tested this for other command, but for the
play command ($03) you can just keep repeating the command and checking
the status returned by that, for bit 6 to go low(and bit 7 to go high in
this case) If you don't and try to do a getloc directly after the play
command reports it's done, the cd will stop. (I guess the cd can't
get it's current location while it's seeking, so the logic stops the seek
to get an exact fix, but never restarts..)


-----------------------------------------------------------------------
19 subcommands.
-----------------------------------------------------------------------

For one reason or another, there is a counter that counts the number of
SCEx strings received by the CD-ROM controller.

Be aware that the results for these commands can exceed 8 bytes.

04: Read SCEx counter (returned in 1st byte?)
05: Reset SCEx counter.  This also sets 1A's SCEx response to
    00 00 00 00, but doesn't appear to force a protection failure.
20: Returns an ASCII string specifying where the CD-ROM firmware is
    intended to be used ("for Japan", "for U/C").
22: Returns a chip number inside the PSX in use.
23: Returns another chip number.
24: Returns yet another chip number.  Same as 22's on some PSXs.

--------------------------------------------------------------------------
3/nov/1999	Initial version
3/feb/2000	Update. Big thanks to Barubary, who rewrote a large part.
--------------------------------------------------------------------------
psx.padua.org                www.padua.org                  doomed@c64.org
--------------------------------------------------------------------------
